package binarysearch;

import org.junit.Test;

/**
 * @Description 剑指 Offer 53 - I. 在排序数组中查找数字 I
 * 与本题类似的有: 34. 在排序数组中查找元素的第一个和最后一个位置 https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/submissions/
 * @Author Firenut
 * @Date 2023-01-21 19:45
 * <p>
 * 目的: 学会求二分的边界值
 */
public class T53_search {
    @Test
    public void test() {
        int[] nums = {5, 7, 7, 8, 8, 10};
        search(nums, 8);
    }


    //法2:时间复杂度为O(logn)
    public int search1(int[] nums, int target) {
        int i, j;
        int left, right;

        //先求右边界
        i = 0;
        j = nums.length - 1;
        while (i <= j) {
            int mid = (i + j) / 2;
            if (nums[mid] <= target) {
                i = mid + 1;
            } else {
                j = mid - 1;
            }
        }
        //如果不存在target
//        if (j >= 0 && nums[j] != target) {
        //j<0的情况：比如数组只有一个元素且没有找到
        if (j < 0 || nums[j] != target) {
            return 0;
        }

        right = i; //记录右边界

        //求左边界
        i = 0;
        j = nums.length - 1;
        while (i <= j) {
            int mid = (i + j) / 2;
            if (nums[mid] < target) {
                i = mid + 1;
            } else { //也就是nums[mid] == target 的情况要让j向左移动
                j = mid - 1;
            }
        }

        //记录左边界
        left = j;

        return right - left - 1;
    }


    //法1:时间复杂度为O(n)
    public int search(int[] nums, int target) {
        int count = 0;
        int index = binarySearch(nums, target);
        //这里是采用了二分查找,但是后面的查找边界操作是O(n),所以没达到O(logn)的效果
        if (index < 0) {
            return 0;
        }
        int len = nums.length;//字符串加括号,数组不用
        count++;
        for (int i = index + 1; i < len; i++) { //向右边找
            if (nums[i] == target) {
                count++;
            } else break;
        }

        for (int i = index - 1; i >= 0; i--) { //向右边找
            if (nums[i] == target) {
                count++;
            } else break;
        }
        return count;
    }

    int binarySearch(int[] nums, int target) {
        int left, right, mid;
        left = 0;
        right = nums.length - 1;
        while (left <= right) {
            mid = (left + right) / 2;
            if (nums[mid] < target) {
                left = mid + 1;
            } else if (nums[mid] == target) {
                return mid;
            } else {
                right = mid - 1;
            }
        }
        return -1;
    }
}
